#include "Main.h"

Unit* FindUnit(DWORD dwId1, DWORD dwId2)
{
	Unit** aUnits = GetUnits();

	if(aUnits)
		for(INT i = 0; i < GetUnitArraySize(); i++)
		{
			Unit* pUnit = aUnits[i];

			if(pUnit->dwID1 == dwId1 && pUnit->dwID2 == dwId2)
				return pUnit;
		}

	return NULL;
}

Unit* FindUnit(DWORD dwSlotOwner, DWORD dwClassId, CHAR* szUnitName, DWORD dwId1, DWORD dwId2, DWORD* dwIndex)
{
	Unit** aUnits = GetUnits();

	if(aUnits)
		for(INT i = 0; i < GetUnitArraySize(); i++)
		{
			Unit* pUnit = aUnits[i];

			if(pUnit->dwOwnerSlot == dwSlotOwner || dwSlotOwner == -1)
				if((pUnit->dwClassId == dwClassId || dwClassId == -1))
					if(!szUnitName || !*szUnitName || strstr(GAME_GetUnitName(pUnit->dwClassId), szUnitName))
						if(dwId1 == pUnit->dwID1 || dwId1 == -1)
							if(dwId2 == pUnit->dwID2 || dwId2 == -1)
							{
								memcpy(dwIndex, &i, sizeof(DWORD));
								return pUnit;
							}
		}

	return NULL;
}

Unit* FindNextUnit(DWORD dwSlotOwner, DWORD dwClassId, CHAR* szUnitName, DWORD dwId1, DWORD dwId2, DWORD* dwIndex)
{
	BOOL bFound = FALSE;
	Unit** aUnits = GetUnits();

	for(INT i = 0; i < GetUnitArraySize(); i++)
	{
		if(!bFound)
		{
			if(aUnits[i]->dwID1 == dwId1 &&
				aUnits[i]->dwID2 == dwId2 && i >= *dwIndex)
				bFound = TRUE;
		} else {
			Unit* pUnit = aUnits[i];

			if(pUnit->dwOwnerSlot == dwSlotOwner || dwSlotOwner == -1)
				if((pUnit->dwClassId == dwClassId || dwClassId == -1))
					if(!szUnitName || !*szUnitName || strstr(GAME_GetUnitName(pUnit->dwClassId), szUnitName))
					{
						memcpy(dwIndex, &i, sizeof(DWORD));
						return pUnit;
					}
		}
	}

	return NULL;
}

DWORD __declspec(naked) __fastcall SetCommandingUnit(DWORD pPlayer,DWORD dwUnitPtr)
{
	__asm
	{
		MOV ECX, [ECX+0x34]
		MOV EAX,DWORD PTR DS:[ECX+0x1E0]
		MOV [ECX+0x1E0], EDX
		RETN
	}
}

VOID __declspec(naked) __fastcall CommandUnit_ASM(DWORD dwPtr, DWORD dwUnitPtr,  DWORD _1, DWORD dwClassId, DWORD _86000001, DWORD _2, DWORD _3, DWORD _4)
{
	__asm {

		//JMP GAME_DoUnitCmd
		PUSH ESI
		MOV ESI, ECX
		MOV EAX, EDX
		XOR EDX, EDX
		JMP GAME_CmdUnit_I
/*
DWORD dwPtr, DWORD _EDX, DWORD _1, DWORD dwClassId, DWORD _86000001, DWORD _2, DWORD _3, DWORD _4), 0x37B830) // Updated
CmdUnit_I
*/
	}
}

VOID CommandUnit(Unit* pUnit, DWORD dwCommand, float fX, float fY, Unit* pTarget, BOOL bOnlyCmd)
{
	Player* pMe = GetPlayer((*p_GAME_GameInfos)->wPlayerSlot);

	if(!pMe)
		return;

	CriticalUnit cUnit;
	cUnit.EnterSection();

	SelectUnitStruct aSelect;	
	memset(&aSelect, NULL, sizeof(SelectUnitStruct));

	// Get a list of all selected units ..
	Unit** pList = GAME_GetSelectedUnits(pMe->dwPtrList, NULL, &aSelect);

	
	if(aSelect.dwSelectedUnits  > 1)
	{
		INT nSize = 4;
		BYTE UnselectUnits[256] = {NULL};

		UnselectUnits[0] = 0x16;
		UnselectUnits[1] = 2;
		UnselectUnits[2] = 2;
		UnselectUnits[3] = 0;

		for(INT i = 0; i < aSelect.dwSelectedUnits; i++)
		{
			*(DWORD*)&UnselectUnits[nSize] = aSelect.pUnitArray[i]->dwID1;
			nSize+=4;
			*(DWORD*)&UnselectUnits[nSize] = aSelect.pUnitArray[i]->dwID2;
			nSize+=4;
		}

		SendPacket(UnselectUnits, nSize);
	} 
	else if(aSelect.dwSelectedUnits) {
		BYTE UnselectUnits[12] = {0};
		UnselectUnits[0] = 0x16;
		UnselectUnits[1] = 2;
		UnselectUnits[2] = 1;
		UnselectUnits[3] = 0;
		*(DWORD*)&UnselectUnits[4] = aSelect.pUnitArray[0]->dwID1;
		*(DWORD*)&UnselectUnits[8] = aSelect.pUnitArray[0]->dwID2;

		SendPacket(UnselectUnits, 12);
	}
	
	BYTE SelectUnit[12] = {0};
	SelectUnit[0] = 0x16;
	SelectUnit[1] = 1;
	SelectUnit[2] = 1;
	SelectUnit[3] = 0;
	*(DWORD*)&SelectUnit[4] = pUnit->dwID1;
	*(DWORD*)&SelectUnit[8] = pUnit->dwID2;

	SendPacket(SelectUnit, 12);

	BYTE bReleaseFocus[1] = {0x1A};
	SendPacket(bReleaseFocus, 1);

	BYTE aPacket2[13] = {0x19, 00, 00, 00, 00,
		00,00,00,00,
		00,00,00,00};

	*(DWORD*)&aPacket2[1] = pUnit->dwClassId;
	*(DWORD*)&aPacket2[5] = pUnit->dwID1;
	*(DWORD*)&aPacket2[9] = pUnit->dwID2;

	SendPacket(aPacket2, 13);

	if(bOnlyCmd)
	{
		DWORD dwOldPtr = SetCommandingUnit((DWORD)pMe, (DWORD)pUnit);
		GAME_DoUnitCmd(GetBuildingRequiredPtr(), NULL, NULL, dwCommand, TRUE, NULL, NULL, NULL);	
		SetCommandingUnit((DWORD)pMe, dwOldPtr);
	}
	else
	if(!pTarget)
		GAME_SendCommandXY(dwCommand,NULL, fX, fY, NULL, 6, NULL);
	else GAME_SendCommandUnit(dwCommand, NULL, pTarget, 4, NULL);

	BYTE UnselectUnits2[12] = {0};
	UnselectUnits2[0] = 0x16;
	UnselectUnits2[1] = 2;
	UnselectUnits2[2] = 1;
	UnselectUnits2[3] = 0;
	*(DWORD*)&UnselectUnits2[4] = pUnit->dwID1;
	*(DWORD*)&UnselectUnits2[8] = pUnit->dwID2;

	SendPacket(UnselectUnits2, 12);

	// Select all units we unselected b4 again
	if(aSelect.dwSelectedUnits  > 1)
	{
		INT nSize = 4;
		BYTE SelectUnits[256] = {NULL};

		SelectUnits[0] = 0x16;
		SelectUnits[1] = 1;
		SelectUnits[2] = 2;
		SelectUnits[3] = 0;

		for(INT i = 0; i < aSelect.dwSelectedUnits; i++)
		{
			*(DWORD*)&SelectUnits[nSize] = aSelect.pUnitArray[i]->dwID1;
			nSize+=4;
			*(DWORD*)&SelectUnits[nSize] = aSelect.pUnitArray[i]->dwID2;
			nSize+=4;
		}

		SendPacket(SelectUnits, nSize);
	}
	else if(aSelect.dwSelectedUnits) {
		BYTE SelectUnit[12] = {0};
		SelectUnit[0] = 0x16;
		SelectUnit[1] = 1;
		SelectUnit[2] = 1;
		SelectUnit[3] = 0;
		*(DWORD*)&SelectUnit[4] = aSelect.pUnitArray[0]->dwID1;
		*(DWORD*)&SelectUnit[8] = aSelect.pUnitArray[0]->dwID2;

		SendPacket(SelectUnit, 12);

		BYTE bReleaseFocus[1] = {0x1A};
		SendPacket(bReleaseFocus, 1);

		BYTE aPacket2[13] = {0x19, 00, 00, 00, 00,
							00,00,00,00,
							00,00,00,00};

		*(DWORD*)&aPacket2[1] = aSelect.pUnitArray[0]->dwClassId;
		*(DWORD*)&aPacket2[5] = aSelect.pUnitArray[0]->dwID1;
		*(DWORD*)&aPacket2[9] = aSelect.pUnitArray[0]->dwID2;

		SendPacket(aPacket2, 13);
	}	
	
}

VOID CommandUnit_Build(Unit* pUnit, float fX, float fY, DWORD dwBuildClassId)
{
	Player* pMe = GetPlayer((*p_GAME_GameInfos)->wPlayerSlot);

	if(!pMe)
		return;

	CriticalUnit cUnit;
	cUnit.EnterSection();

	SelectUnitStruct aSelect;	
	memset(&aSelect, NULL, sizeof(SelectUnitStruct));

	// Get a list of all selected units ..
	Unit** pList = GAME_GetSelectedUnits(pMe->dwPtrList, NULL, &aSelect);

	
	if(aSelect.dwSelectedUnits  > 1)
	{
		INT nSize = 4;
		BYTE UnselectUnits[256] = {NULL};

		UnselectUnits[0] = 0x16;
		UnselectUnits[1] = 2;
		UnselectUnits[2] = 2;
		UnselectUnits[3] = 0;

		for(INT i = 0; i < aSelect.dwSelectedUnits; i++)
		{
			*(DWORD*)&UnselectUnits[nSize] = aSelect.pUnitArray[i]->dwID1;
			nSize+=4;
			*(DWORD*)&UnselectUnits[nSize] = aSelect.pUnitArray[i]->dwID2;
			nSize+=4;
		}

		SendPacket(UnselectUnits, nSize);
	} 
	else if(aSelect.dwSelectedUnits) {
		BYTE UnselectUnits[12] = {0};
		UnselectUnits[0] = 0x16;
		UnselectUnits[1] = 2;
		UnselectUnits[2] = 1;
		UnselectUnits[3] = 0;
		*(DWORD*)&UnselectUnits[4] = aSelect.pUnitArray[0]->dwID1;
		*(DWORD*)&UnselectUnits[8] = aSelect.pUnitArray[0]->dwID2;

		SendPacket(UnselectUnits, 12);
	}
	
	BYTE SelectUnit[12] = {0};
	SelectUnit[0] = 0x16;
	SelectUnit[1] = 1;
	SelectUnit[2] = 1;
	SelectUnit[3] = 0;
	*(DWORD*)&SelectUnit[4] = pUnit->dwID1;
	*(DWORD*)&SelectUnit[8] = pUnit->dwID2;

	SendPacket(SelectUnit, 12);

	BYTE bReleaseFocus[1] = {0x1A};
	SendPacket(bReleaseFocus, 1);

	BYTE aPacket2[13] = {0x19, 00, 00, 00, 00,
		00,00,00,00,
		00,00,00,00};

	*(DWORD*)&aPacket2[1] = pUnit->dwClassId;
	*(DWORD*)&aPacket2[5] = pUnit->dwID1;
	*(DWORD*)&aPacket2[9] = pUnit->dwID2;

	SendPacket(aPacket2, 13);

	BYTE aPacket3[1] = {0x67};
	
	SendPacket(aPacket3, 1);
	GAME_BuildXY(dwBuildClassId, NULL, &fX, &fY, 4);

	BYTE UnselectUnits2[12] = {0};
	UnselectUnits2[0] = 0x16;
	UnselectUnits2[1] = 2;
	UnselectUnits2[2] = 1;
	UnselectUnits2[3] = 0;
	*(DWORD*)&UnselectUnits2[4] = pUnit->dwID1;
	*(DWORD*)&UnselectUnits2[8] = pUnit->dwID2;

	SendPacket(UnselectUnits2, 12);

	// Select all units we unselected b4 again
	if(aSelect.dwSelectedUnits  > 1)
	{
		INT nSize = 4;
		BYTE SelectUnits[256] = {NULL};

		SelectUnits[0] = 0x16;
		SelectUnits[1] = 1;
		SelectUnits[2] = 2;
		SelectUnits[3] = 0;

		for(INT i = 0; i < aSelect.dwSelectedUnits; i++)
		{
			*(DWORD*)&SelectUnits[nSize] = aSelect.pUnitArray[i]->dwID1;
			nSize+=4;
			*(DWORD*)&SelectUnits[nSize] = aSelect.pUnitArray[i]->dwID2;
			nSize+=4;
		}

		SendPacket(SelectUnits, nSize);
	}
	else if(aSelect.dwSelectedUnits) {
		BYTE SelectUnit[12] = {0};
		SelectUnit[0] = 0x16;
		SelectUnit[1] = 1;
		SelectUnit[2] = 1;
		SelectUnit[3] = 0;
		*(DWORD*)&SelectUnit[4] = aSelect.pUnitArray[0]->dwID1;
		*(DWORD*)&SelectUnit[8] = aSelect.pUnitArray[0]->dwID2;

		SendPacket(SelectUnit, 12);

		BYTE bReleaseFocus[1] = {0x1A};
		SendPacket(bReleaseFocus, 1);

		BYTE aPacket2[13] = {0x19, 00, 00, 00, 00,
							00,00,00,00,
							00,00,00,00};

		*(DWORD*)&aPacket2[1] = aSelect.pUnitArray[0]->dwClassId;
		*(DWORD*)&aPacket2[5] = aSelect.pUnitArray[0]->dwID1;
		*(DWORD*)&aPacket2[9] = aSelect.pUnitArray[0]->dwID2;

		SendPacket(aPacket2, 13);
	}	
	
}